package Timer;

import java.util.PriorityQueue;

//通过这个类描述一个任务
class MyTimerTask implements Comparable<MyTimerTask>{
    //在什么时间来执行这个任务
    //约定这个time是ms级别的时间戳
    private long time;
    //实际执行的代码
    private Runnable runnable;

    //delay期望是一个“相对时间”
    public MyTimerTask(Runnable runnable,long delay){
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + delay;
    }

    public void run(){
        runnable.run();
    }

    @Override
    public int compareTo(MyTimerTask o) {
        return (int) (this.time - o.time);//比较时间
    }

    public long getTime(){
        return time;
    }
}

//通过这个类表示一个定时器
class MyTimer{

    //任务队列
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();
    //搞个锁对象
    private Object locker = new Object();

    public void schedule(Runnable runnable,long delay){
        synchronized (locker){
            MyTimerTask task = new MyTimerTask(runnable,delay);
            queue.offer(task);//入队

            locker.notify();//添加新元素后就可以唤醒
        }

    }

    //构造方法，创建扫描线程，让扫描线程进行判定和扫描
    public MyTimer(){
       Thread t = new Thread(() ->{
           //扫描线程就需要循环的反复的扫描队首元素，然后判定队首元素是不是时间到了
            // 如果时间没到，就啥都不干
            //如果时间到了，就把这个任务从队列中删除掉

            while (true){
                synchronized (locker){
                    while (queue.isEmpty()){
                        try {
                            locker.wait();//在入队时候唤醒
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }

                    MyTimerTask task = queue.peek();
                    //获取当前时间
                    long curTime = System.currentTimeMillis();

                    if(curTime >= task.getTime()){
                        //时间到了执行任务
                        queue.poll();
                        task.run();
                    }else {
                        //时间没到
                        try {
                            locker.wait(task.getTime() - curTime);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }

            }
        });

        t.start();
    }

}

public class Main {
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("3000");
            }
        },3000);

        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("2000");
            }
        },2000);
    }
}
